package com.korion.andsurfacewallpaperdemo.gl

import android.content.Context
import android.graphics.SurfaceTexture
import android.opengl.GLES11Ext
import android.opengl.GLES20
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer

class VideoRenderer(private val context: Context) {
    private var program = 0
    private var textureId = -1
    private var surfaceTexture: SurfaceTexture? = null
    
    private var aPositionLocation = 0
    private var aTextureCoordLocation = 0
    private var uTextureMatrixLocation = 0
    private var uAlphaLocation = 0
    
    private lateinit var vertexBuffer: FloatBuffer
    private lateinit var textureBuffer: FloatBuffer
    
    private val vertexData = floatArrayOf(
        -1f, -1f,
        1f, -1f,
        -1f, 1f,
        1f, 1f
    )
    
    private val textureData = floatArrayOf(
        0f, 1f,
        1f, 1f,
        0f, 0f,
        1f, 0f
    )
    
    private var alpha = 0.5f // 默认半透明
    
    init {
        vertexBuffer = ByteBuffer.allocateDirect(vertexData.size * 4)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer()
        vertexBuffer.put(vertexData).position(0)
        
        textureBuffer = ByteBuffer.allocateDirect(textureData.size * 4)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer()
        textureBuffer.put(textureData).position(0)
    }
    
    fun initGL() {
        val vertexShaderSource = ShaderHelper.readShaderFromAssets(context, context.resources.getIdentifier("video_vertex", "raw", context.packageName))
        val fragmentShaderSource = ShaderHelper.readShaderFromAssets(context, context.resources.getIdentifier("video_fragment", "raw", context.packageName))
        
        program = ShaderHelper.buildProgram(vertexShaderSource, fragmentShaderSource)
        
        aPositionLocation = GLES20.glGetAttribLocation(program, "aPosition")
        aTextureCoordLocation = GLES20.glGetAttribLocation(program, "aTextureCoord")
        uTextureMatrixLocation = GLES20.glGetUniformLocation(program, "uTextureMatrix")
        uAlphaLocation = GLES20.glGetUniformLocation(program, "uAlpha")
        
        textureId = createTextureID()
        surfaceTexture = SurfaceTexture(textureId)
    }
    
    fun drawFrame(stMatrix: FloatArray?) {
        GLES20.glUseProgram(program)
        
        // 设置顶点坐标
        vertexBuffer.position(0)
        GLES20.glVertexAttribPointer(aPositionLocation, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer)
        GLES20.glEnableVertexAttribArray(aPositionLocation)
        
        // 设置纹理坐标
        textureBuffer.position(0)
        GLES20.glVertexAttribPointer(aTextureCoordLocation, 2, GLES20.GL_FLOAT, false, 0, textureBuffer)
        GLES20.glEnableVertexAttribArray(aTextureCoordLocation)
        
        // 更新SurfaceTexture
        surfaceTexture?.updateTexImage()
        
        // 设置纹理矩阵
        if (stMatrix != null) {
            GLES20.glUniformMatrix4fv(uTextureMatrixLocation, 1, false, stMatrix, 0)
        }
        
        // 设置透明度
        GLES20.glUniform1f(uAlphaLocation, alpha)
        
        // 绘制
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
        
        GLES20.glDisableVertexAttribArray(aPositionLocation)
        GLES20.glDisableVertexAttribArray(aTextureCoordLocation)
    }
    
    fun setAlpha(alpha: Float) {
        this.alpha = alpha
    }
    
    fun getSurfaceTexture(): SurfaceTexture? {
        return surfaceTexture
    }
    
    fun getTextureId(): Int {
        return textureId
    }
    
    private fun createTextureID(): Int {
        val texture = IntArray(1)
        GLES20.glGenTextures(1, texture, 0)
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture[0])
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR.toFloat())
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat())
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE)
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE)
        return texture[0]
    }
    
    fun release() {
        surfaceTexture?.release()
        GLES20.glDeleteTextures(1, intArrayOf(textureId), 0)
        GLES20.glDeleteProgram(program)
    }
}